// Copyright 2021 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Author: Matheus Cavalcante <matheusd@iis.ee.ethz.ch>
//         Basile Bougenot <bbougenot@student.ethz.ch>

#include "vector_macros.h"

void TEST_CASE1() {
  VSET(16, e16, m1);
  VLOAD_16(v6, 0x4c8e, 0xd449, 0xe266, 0xb6d1, 0xf28a, 0x1655, 0x3111, 0x4bde, 0x8787, 0x2ce4, 0x1083, 0xaa0c, 0x9fdf, 0x3e42, 0x98e7, 0xe33b);
  VSET(16, e8, m1);
  uint64_t scalar = 5;
  VLOAD_8(v4, 0x83, 0xfe, 0xa2, 0xc3, 0xa6, 0x18, 0xd9, 0x4c, 0x6e, 0xeb, 0x43, 0xb7, 0xec, 0x48, 0xb7, 0xe5);
  asm volatile("vwmaccus.vx v6, %[A], v4" :: [A] "r" (scalar));
  VSET(16, e16, m1);
  VCMP_I16(1, v6, 0x4a1d, 0xd43f, 0xe090, 0xb5a0, 0xf0c8, 0x16cd, 0x304e, 0x4d5a, 0x89ad, 0x2c7b, 0x11d2, 0xa89f, 0x9f7b, 0x3faa, 0x977a, 0xe2b4);

  VSET(16, e32, m1);
  VLOAD_32(v6, 0xe318cc7a, 0x489815a8, 0x6e6fc053, 0x8d746807, 0xbc3e6244, 0xcdfeb4fe, 0x22d24149, 0x26962240, 0x5ef85b7e, 0x2f61a9e8, 0x373dc202, 0x1567a6b5, 0x763c5239, 0x60dd0502, 0xab178102, 0x753e0a11);
  VSET(16, e16, m1);
  scalar = 5383;
  VLOAD_16(v4, 0xce02, 0x6935, 0xc803, 0x75bc, 0x80b7, 0x19d2, 0x3b7c, 0xc269, 0xb639, 0x66f1, 0x678b, 0xc83e, 0x5a5c, 0x389e, 0x9e46, 0xfae9);
  asm volatile("vwmaccus.vx v6, %[A], v4" :: [A] "r" (scalar));
  VSET(16, e32, m1);
  VCMP_I32(2, v6, 0xdefd9888, 0x513c4f1b, 0x69d67768, 0x97200c2b, 0xb1c9ea45, 0xd01da3bc, 0x27b50dad, 0x2187101f, 0x58e9040d, 0x37d63f7f, 0x3fbefdcf, 0x10d33667, 0x7da856bd, 0x65838754, 0xa31092ec, 0x74d30370);

  VSET(16, e64, m1);
  VLOAD_64(v6, 0xb6a5b1c3c6d69abb, 0x3c6a647eb0d79a41, 0xf0c3eb8821045259, 0x91d74be946352cae, 0x524c6db6c58f9da6, 0x39185a920f7787e8, 0x4080fbf0fdcc64ec, 0x9ed1fb83f53270fc, 0xff0661a19269f0c0, 0x47d26c599193fe0b, 0xd8cc0342dc3104ce, 0xc51f802bc93381cd, 0xe7d6522aa1c51245, 0x6fa0a9d3f57bc667, 0xd140731478a147a8, 0x5d716379591922f4);
  VSET(16, e32, m1);
  scalar = 6474219;
  VLOAD_32(v4, 0x09377def, 0x99ee4d30, 0x8b8452d1, 0xc9e17667, 0x2254aa29, 0xb56ca9f5, 0xa1276371, 0x32ac1413, 0x59ff6af3, 0x6b61bf57, 0xc0eb37b3, 0x26f06be7, 0x0e9b21b2, 0x22898a93, 0xe3646841, 0xdd301fdc);
  asm volatile("vwmaccus.vx v6, %[A], v4" :: [A] "r" (scalar));
  VSET(16, e64, m1);
  VCMP_I64(3, v6, 0xb6a940470425dc20, 0x3c430136a5932551, 0xf096f84fcc847134, 0x91c26988f191bc3b, 0x5259ad33e6940249, 0x38fb9358fb72e8cf, 0x405c6235eb4a66a7, 0x9ee5895b4431c96d, 0xff291c64abdfe8d1, 0x47fbdc7722d7f1e8, 0xd8b3ab8cf55eb11f, 0xc52e86eb9b0cedda, 0xe7dbf512bdc5c2ab, 0x6fadfdb8b3d16658, 0xd13568f3f48a0453, 0x5d63f4705f821de8);
}

void TEST_CASE2() {
  VSET(16, e16, m1);
  VLOAD_16(v6, 0x4c8e, 0xd449, 0xe266, 0xb6d1, 0xf28a, 0x1655, 0x3111, 0x4bde, 0x8787, 0x2ce4, 0x1083, 0xaa0c, 0x9fdf, 0x3e42, 0x98e7, 0xe33b);
  VSET(16, e8, m1);
  uint64_t scalar = 5;
  VLOAD_8(v4, 0x83, 0xfe, 0xa2, 0xc3, 0xa6, 0x18, 0xd9, 0x4c, 0x6e, 0xeb, 0x43, 0xb7, 0xec, 0x48, 0xb7, 0xe5);
  VLOAD_8(v0, 0xAA, 0xAA);
  asm volatile("vwmaccus.vx v6, %[A], v4, v0.t" :: [A] "r" (scalar));
  VSET(16, e16, m1);
  VCMP_I16(4, v6, 0x4c8e, 0xd43f, 0xe266, 0xb5a0, 0xf28a, 0x16cd, 0x3111, 0x4d5a, 0x8787, 0x2c7b, 0x1083, 0xa89f, 0x9fdf, 0x3faa, 0x98e7, 0xe2b4);

  VSET(16, e32, m1);
  VLOAD_32(v6, 0xe318cc7a, 0x489815a8, 0x6e6fc053, 0x8d746807, 0xbc3e6244, 0xcdfeb4fe, 0x22d24149, 0x26962240, 0x5ef85b7e, 0x2f61a9e8, 0x373dc202, 0x1567a6b5, 0x763c5239, 0x60dd0502, 0xab178102, 0x753e0a11);
  VSET(16, e16, m1);
  scalar = 5383;
  VLOAD_16(v4, 0xce02, 0x6935, 0xc803, 0x75bc, 0x80b7, 0x19d2, 0x3b7c, 0xc269, 0xb639, 0x66f1, 0x678b, 0xc83e, 0x5a5c, 0x389e, 0x9e46, 0xfae9);
  VLOAD_8(v0, 0xAA, 0xAA);
  asm volatile("vwmaccus.vx v6, %[A], v4, v0.t" :: [A] "r" (scalar));
  VSET(16, e32, m1);
  VCMP_I32(5, v6, 0xe318cc7a, 0x513c4f1b, 0x6e6fc053, 0x97200c2b, 0xbc3e6244, 0xd01da3bc, 0x22d24149, 0x2187101f, 0x5ef85b7e, 0x37d63f7f, 0x373dc202, 0x10d33667, 0x763c5239, 0x65838754, 0xab178102, 0x74d30370);

  VSET(16, e64, m1);
  VLOAD_64(v6, 0xb6a5b1c3c6d69abb, 0x3c6a647eb0d79a41, 0xf0c3eb8821045259, 0x91d74be946352cae, 0x524c6db6c58f9da6, 0x39185a920f7787e8, 0x4080fbf0fdcc64ec, 0x9ed1fb83f53270fc, 0xff0661a19269f0c0, 0x47d26c599193fe0b, 0xd8cc0342dc3104ce, 0xc51f802bc93381cd, 0xe7d6522aa1c51245, 0x6fa0a9d3f57bc667, 0xd140731478a147a8, 0x5d716379591922f4);
  VSET(16, e32, m1);
  scalar = 6474219;
  VLOAD_32(v4, 0x09377def, 0x99ee4d30, 0x8b8452d1, 0xc9e17667, 0x2254aa29, 0xb56ca9f5, 0xa1276371, 0x32ac1413, 0x59ff6af3, 0x6b61bf57, 0xc0eb37b3, 0x26f06be7, 0x0e9b21b2, 0x22898a93, 0xe3646841, 0xdd301fdc);
  VLOAD_8(v0, 0xAA, 0xAA);
  asm volatile("vwmaccus.vx v6, %[A], v4, v0.t" :: [A] "r" (scalar));
  VSET(16, e64, m1);
  VCMP_I64(6, v6, 0xb6a5b1c3c6d69abb, 0x3c430136a5932551, 0xf0c3eb8821045259, 0x91c26988f191bc3b, 0x524c6db6c58f9da6, 0x38fb9358fb72e8cf, 0x4080fbf0fdcc64ec, 0x9ee5895b4431c96d, 0xff0661a19269f0c0, 0x47fbdc7722d7f1e8, 0xd8cc0342dc3104ce, 0xc52e86eb9b0cedda, 0xe7d6522aa1c51245, 0x6fadfdb8b3d16658, 0xd140731478a147a8, 0x5d63f4705f821de8);
}

int main(void){
  INIT_CHECK();
  enable_vec();

  TEST_CASE1();
  TEST_CASE2();

  EXIT_CHECK();
}
